
/**
 * Clase que representa el problema de los misioneros
 *
 */

package Problemas;

import Busquedas.Estado;

public class Misioneros extends Problema {
		
	int NM;
	
	int NC;
	
	int B;
	
	
	
	/**
	 * Constructor de la clase
	 */
	public Misioneros() {
		int[] paramInicial = {3,3,1};
		int[] paramObjetivo = {0,0,0};
		Estado inicial = new Estado(paramInicial);
		Estado[] objetivo = new Estado[1];
		objetivo[0] = new Estado(paramObjetivo);		
		String [] nombresOperadores={"padre","cruzaM","cruzaC","cruzaMM","cruzaCC","cruzaMC"};
		int [] costeOperadores={1,1,1,1,1};		
		inicializa(inicial,objetivo,5,nombresOperadores,costeOperadores);
			
	}
	
	
	/**
	 * asigna los parametros del estado dado.
	 * @param e estado dado.
	 */
	public void asignaParametros(Estado e){
		NM = e.getParametro(0);
		NC = e.getParametro(1);
		B = e.getParametro(2);
	}
	
	/** Devuelve si es un estado de peligro
	 * @param e estado que comprobamos
	 * @return si es de peligro
	 */
	public boolean peligro(Estado e){
		asignaParametros(e);
		return ((NM < NC) && (NM != 0)) || ((NM > NC) && (NM != 3));
	}
	
 	/**
	 * Cruza un misionero
	 *  Devolver� null si no se puede aplicar el operador
	 * @param actual estado en el que nos encontramos
	 * @return estado resultante
	 */
	public Estado cruzaM(Estado actual){
		Estado aux;
		asignaParametros(actual);
		if (B == 1 && NM > 0){
			B = 0;
			NM--;
		}else if(B == 0 && NM < 3){
			B = 1;
			NM++;
		}else{
			return null;
		}
		int[] param = {NM,NC,B};
		aux = new Estado(param);
		if (peligro(aux)){
			return null;
		}
		return aux;
	}
	
	
	/**
	 * Cruza dos misioneros
	 *  Devolver� null si no se puede aplicar el operador
	 * @param actual estado en el que nos encontramos
	 * @return estado resultante
	 */
	public Estado cruzaMM(Estado actual){
		Estado aux;
		asignaParametros(actual);
		if (B == 1 && NM > 1){
			B = 0;
			NM = NM-2;
		}else if(B == 0 && NM < 2){
			B = 1;
			NM = NM+2;
		}else
			return null;
		int[] param = {NM,NC,B};
		aux = new Estado(param);
		if (peligro(aux)){
			return null;
		}
		return aux;		
	}
	
	
	/**
	 * Cruza un canibal
	 *  Devolver� null si no se puede aplicar el operador
	 * @param actual estado en el que nos encontramos
	 * @return estado resultante
	 */
	public Estado cruzaC(Estado actual){
		Estado aux;
		asignaParametros(actual);
		if (B == 1 && NC > 0){
			B = 0;
			NC--;
		}else if(B == 0 && NC < 3){
			B = 1;
			NC++;
		}else{
			return null;
		}
		int[] param = {NM,NC,B};
		aux = new Estado(param);
		if (peligro(aux)){
			return null;
		}
		return aux;
	}
	
	
	/**
	 * Cruza dos canibales
	 *  Devolver� null si no se puede aplicar el operador
	 * @param actual estado en el que nos encontramos
	 * @return estado resultante
	 */
	public Estado cruzaCC(Estado actual){
		Estado aux;
		asignaParametros(actual);
		if (B == 1 && NC > 1){
			B = 0;
			NC = NC-2;
		}else if(B == 0 && NC < 2){
			B = 1;
			NC = NC+2;
		}else
			return null;
		int[] param = {NM,NC,B};
		aux = new Estado(param);
		if (peligro(aux)){
			return null;
		}
		return aux;		
	}
	
	/**
	 * Cruza un misionero y un canibal
	 *  Devolver� null si no se puede aplicar el operador
	 * @param actual estado en el que nos encontramos
	 * @return estado resultante
	 */
	public Estado cruzaMC(Estado actual){
		Estado aux;
		asignaParametros(actual);
		if (B == 1 && NM > 0 && NC > 0){
			B = 0;
			NM--;
			NC--;
		}else if(B == 0 && NM < 3 && NC < 3){
			B = 1;
			NM++;
			NC++;
		}else
			return null;
		int[] param = {NM,NC,B};
		aux = new Estado(param);
		if (peligro(aux)){
			return null;
		}
		return aux;		
	}
	
	/* (non-Javadoc)
	 * @see Problema#getOperadorInverso(int)
	 */
	public int getOperadorInverso(int op){

        //al volver aplicar el mismo operador retornas al estado anterior
        return op;
	}
	
	
	/* (non-Javadoc)
	 * @see Problema#aplicaOperador(Estado, int)
	 */
	public Estado aplicaOperador(Estado actual,int i){
		Estado siguiente = null;
		switch(i){
		case 0:
			siguiente = cruzaM(actual);
			break;
		case 1:
			siguiente = cruzaC(actual);
			break;
		case 2:
			siguiente = cruzaMM(actual);
			break;
		case 3:
			siguiente = cruzaCC(actual);
			break;
		case 4:
			siguiente = cruzaMC(actual);
			break;
		}
		return siguiente;
	}	
       public int funcionHeuristica(Estado estado){

       int hVal = NM + NC - B;
	   return hVal;
		
	}
 

}
